import {PromiseMabe, ValueDefine, DataResult, ValueStartWatchOption} from "./types";

export type DynamicWatchValue<T> =
    T |
    (() => PromiseMabe<T>) |
    { $watch: () => PromiseMabe<T> } |
    { $watch: () => PromiseMabe<any>, $then: (args: any) => PromiseMabe<T> }

export type DataSourceParams<T> = (() => PromiseMabe<T>) | { [key: string]: DynamicWatchValue<any> }

export type DataSourceInvokeOption<T> = (...args: any[]) => DataResult<T>

export interface DataSourceOptionBase {
    /**
     * 请求前回调 ( 直接赋值 data 不会走这个回调), this 为 scope 对象
     * @param owner 发出者
     * @param request 请求源
     * @return
     *   如果返回 null 数据则清空 []
     *   如果返回 undefined , 则不拦截（继续调用）
     *   如果返回 any[] 或 Promise<any[]> 则取消请求，以返回值为主
     */
    onBefore?: (owner: any, request: any) => DataResult<any[]>

    /**
     * 返回值后回调, this 为 scope 对象
     * @param owner 发出者
     * @param result 执行结果
     * @param request 请求源
     * @return
     *   如果返回了 null , 则取消本次加载的数据（不要影响现有 data）
     *   如果函数返回 undefined 数据以 dataOrgin 为主
     *   如果返回了 any[] 或 Promise<any[]> 则以返回值为主
     */
    onAfter?: (owner: any, result: any, request: any) => DataResult<any[]>

    /**
     * 数据加载完毕后回调. this 为 scope 对象
     * @param owner 发出者
     */
    onFinish?: (owner: any) => void

    /**
     * 用来与 key->value 类型组件（select / checkboxGroup / radio / cascader）绑定时，值字段名(默认 "value" 属性, 表格默认 "id" 属性)
     */
    idField?: string

    /**
     * 用来与 key->value 类型组件（select / checkboxGroup / radio / cascader）绑定时，显示字段名(默认 "label" 属性)
     */
    labelField?: string

    /**
     * 用来与 key->value 类型组件（select / checkboxGroup / radio / cascader）绑定时，起禁用作用的字段名，该字段没有默认值，默认不启用 disabled
     */
    disabledField?: string

    /**
     * 用来生成树形结构的组件（tree / cascader）绑定时，指定父字段名
     * 如果树形组件不设置该属性，则以层级的方式 children: [] 指定下级
     */
    parentField?: string
}

export interface DataSourceAjaxOption<T> extends DataSourceOptionBase {
    url: DynamicWatchValue<string>
    method: 'post' | 'get' | 'delete' | 'post-json'
    params?: DataSourceParams<T>
}

export interface DataSourceFuncOption<T> extends DataSourceOptionBase {
    func: (...args: any[]) => DataResult<T>
    params?: DataSourceParams<T>
}

export type DataSourceOption<T> =
    T |
    DataSourceAjaxOption<T> |
    DataSourceFuncOption<T> |
    DataSourceInvokeOption<T>

/**
 * 数据源观察者（取值者）
 * this.watch({
 *     url: '',
 *     method: '',
 *     params: {
 *          param1: '',
 *          param1: ()=>{},
 *          param2: {$watch=>(), $then=>{}}
 *     }
 * })
 *
 * this.watch(()=>{},
 *     'a'                              //arg1
 *     ()=>{},                          //arg2
 *     {$watch:()=>{}, $then:()=>{}}    //arg3
 * )
 *
 * vjson.title = this.watch().then()
 */
export class DataSourceWatcher<T> extends ValueDefine<T> {

    /**
     * 数据源配置
     */
    readonly func: () => PromiseMabe<T>
    readonly scope: any

    constructor(scope: any, func: () => PromiseMabe<T>) {
        super()
        this.scope = scope
        this.func = func
    }

    /**
     * 开启监听
     */
    start(executeOption: ValueStartWatchOption): void {

    }

    /**
     * 只获取执行结果，不监听，不用 dispose
     */
    get(): Promise<T> {
        // @ts-ignore
        return this.func.call(this.scope);
    }

    /**
     * 结束监听, 结束对象
     */
    dispose(): void {

    }
}